package com.example.merchantdemo.callback.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.merchantdemo.callback.dto.AcceptCallbackReq;
import com.example.merchantdemo.callback.dto.AcceptCallbackResp;
import com.example.merchantdemo.callback.dto.AcceptSellCoinOrderStatusPushReq;
import com.example.merchantdemo.callback.dto.AcceptSellCoinOrderStatusPushResp;
import com.example.merchantdemo.callback.service.CallbackService;
import com.example.merchantdemo.constants.SecretKeyConstant;
import com.example.merchantdemo.util.SignatureGenerateHelper;
import org.springframework.stereotype.Service;

/**
 * 回调服务实现类
 */
@Service
public class CallbackServiceImpl implements CallbackService {

    /**
     * 接受支付平台回调
     *
     * @param req
     */
    @Override
    public AcceptCallbackResp acceptCallback(AcceptCallbackReq req) {

        // 接收到推送数据后，先验签，验签通过方可信任，继续进行下面的操作
        boolean verifyResult = SignatureGenerateHelper.verifyRSASign(SecretKeyConstant.PLATFORM_PUBLIC_KEY,
                JSONObject.toJSONString(req), req.getMerchantSign());

        if (!verifyResult) {
            throw new RuntimeException("验证签名失败");
        }

        // 平台会将成功的订单推送给商户，这里需要写商户在接到成功订单后，在商户端的处理逻辑(给用户加币)
        // TODO 一定要注意: 这里修改商户订单状态时需要加锁(例如用数据库行锁锁住)，防止并发(如果不锁住可能会走两次业务逻辑)。
        //  此接口需保证同一个订单号调用此接口两次，只能处理第一次，第二次请求过来时这个订单已完成，无需再处理。

        // 若商户选择用户支付手续费时，验签后，将推送金额作为基数，这里扣除手续费后，也就是 推送金额-扣除手续费 = 实际该给用户冲的数量，
        // 这部分逻辑需要商户端自行处理，这里只给出实现思路

        //处理完成后,需给平台返回code为200，平台会视为本次推送成功
        AcceptCallbackResp resp = new AcceptCallbackResp();
        resp.setCode(200);

        return resp;

    }

    /**
     * 接收卖币订单状态推送:
     * 此接口的作用是: 卖币时商户冻结了用户的币，然后生成了商户订单。支付平台会将交易的结果(成功或失败)推送到商户这里，
     * 如果交易结果是成功，将用户冻结的币扣除 ; 如果交易结果是失败，将用户冻结的币解冻并退回。
     *
     * @param req
     * @return
     */
    @Override
    public AcceptSellCoinOrderStatusPushResp acceptSellCoinOrderStatusPush(AcceptSellCoinOrderStatusPushReq req) {

        // 先验签，验签通过后方可信任
        boolean verifyResult = SignatureGenerateHelper.verifyRSASign(SecretKeyConstant.PLATFORM_PUBLIC_KEY,
                JSONObject.toJSONString(req), req.getMerchantSign());

        if (!verifyResult) {
            throw new RuntimeException("签名验证失败");
        }

        // 这里根据 req 中 orderCurrentStatus  的状态来执行不同的逻辑
        // TODO 这里需要保证无论是将用户冻结的币扣除，还是将冻结的币解冻并退回，这段逻辑只执行一次。建议修改商户端订单状态时，
        //  先检查订单状态，并加锁(例如数据库行锁)，防止并发。




        //处理完成后,需给平台返回code为200，平台会视为本次推送成功
        AcceptSellCoinOrderStatusPushResp resp = new AcceptSellCoinOrderStatusPushResp();
        resp.setCode(200);

        return resp;

    }
}
